#include "BitStream.h"

namespace onet
{

//! Some specialized implementations
//! Makes it easy to improve the BitStreams perfomance without modifining the methods-names
//! (by adding new templates etc)
template<> void BitStream::writeArray<f32>(const std::vector<f32> &value, const bool resize)
{
    s32 temp;
    c8 size = c8(value.size());
    this->write<c8>(size, resize);

    if(resize)
        buffer.resize((bitIndex+(sizeof(float)*8*size)+7)/8);

    for(c8 cycleArray = 0; cycleArray < size; ++cycleArray)
    {
        memcpy(&temp,&value[cycleArray],sizeof(f32));
        write<s32>(temp, resize);
    }
}

template<> void BitStream::write<bool>(const bool value, const bool resize)
{
    if(resize)
        buffer.resize((bitIndex+8)/8);

    buffer[(bitIndex)/8] |= (value)<<(7-(bitIndex)%8);
    bitIndex++;
}

template<> void BitStream::write<std::string>(std::string value, const bool resize)
{
    write<c8>(c8(value.size()), resize);

    if(resize)
        buffer.resize((bitIndex+((value.size())*8)+7)/8);

    for(std::string::iterator it = value.begin(); it != value.end(); it++)
    {
        this->write<c8>(*it, false);
    }
}

template<> void BitStream::write<f32>(const f32 value, const bool resize)
{
    s32 Temp;
    memcpy(&Temp,&value,sizeof(f32));

    this->write<s32>(Temp, resize);
}

template<> bool BitStream::read<bool>(const bool increment)
{
    bool value = (buffer[bitIndex/8] >> (7-bitIndex%8)) & 0x1;

    if(increment)
        bitIndex++;

    return value;
}

template<> f32 BitStream::read<f32>(const bool increment)
{
    s32 temp = read<s32>(increment);
    f32 value;
    memcpy(&value, &temp, sizeof(f32));

    return value;
}

template<> std::vector<f32> BitStream::readArray<f32>(const bool increment)
{
    s32 temp;
    c8 size = read<c8>(true);
    std::vector<f32> value;
    value.resize(size);

    for(c8 cycleArray = 0; cycleArray < size; cycleArray++)
    {
        temp = read<s32>(true);
        memcpy(&value[cycleArray], &temp, sizeof(f32));
    }

    if(!increment)
        bitIndex -= sizeof(f32)*8*size+8;

    return value;
}

template<> std::string BitStream::read<std::string>(const bool increment)
{
    std::string value;
    s32 length = read<c8>(true);
    value.resize(length);

    for(std::string::iterator stringItr = value.begin(); stringItr != value.end(); stringItr++)
    {
        this->read<c8>(true);
    }

    if(!increment)
        bitIndex -= length*8 + 8;

    return value;
}

}
